home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / vg-2.03 / video / svga.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  9.4 KB  |  491 lines

  1. /*
  2.  * Copyright (C) 1990, 1991 by Michael Davidson.
  3.  * All rights reserved.
  4.  *
  5.  * Permission to use, copy, modify, and distribute this software
  6.  * and its documentation for any purpose and without fee is hereby
  7.  * granted, provided that the above copyright notice appear in all
  8.  * copies and that both that copyright notice and this permission
  9.  * notice appear in supporting documentation.
  10.  *
  11.  * This software is provided "as is" without express or implied warranty.
  12.  */
  13.  
  14. /*
  15.  * svga.c    - support routines for SVGA cards
  16.  */
  17.  
  18. #include    <stdlib.h>
  19. #include    "video.h"
  20. #include    "vdev.h"
  21. #include    "v86types.h"
  22. #include    "vbios.h"
  23. #include    "svga.h"
  24.  
  25. struct svga_mode_info    *SVGAModeTable;
  26. struct svga_mode_info    *SVGAModeInfo;
  27. int            SVGAMaxModeIndex;
  28.  
  29. static int    svga_bios_initial_mode    = -1;
  30. /*
  31.  * svga_reset()
  32.  */
  33. static void
  34. svga_reset()
  35. {
  36.     if (svga_bios_initial_mode != -1)
  37.     VBiosSetMode(svga_bios_initial_mode);
  38. }
  39.  
  40. /*
  41.  * svga_setmode()
  42.  */
  43. static int
  44. svga_setmode(
  45.     int        i
  46.     )
  47. {
  48.     struct svga_mode_info    *s;
  49.  
  50.     if (i < 0 || i > SVGAMaxModeIndex)
  51.     return -1;
  52.  
  53.     s = &SVGAModeTable[i];
  54.  
  55.     VBiosSetMode(s->bios_mode | 0x80);
  56.     if ((VBiosGetMode() & 0x7f) != s->bios_mode)
  57.     return -1;
  58.  
  59.     if (s->attributes & SVGA_TEXT_MODE)        /* text mode */
  60.     {
  61.     VBiosDisableBlink();
  62.     VBiosSetCursorPosition(s->width, s->height);
  63.     }
  64.  
  65.     /*
  66.      * make sure start address is 0
  67.      */
  68.     outw(0x3d4, 0x000c);
  69.     outw(0x3d4, 0x000d);
  70.  
  71.     if (s->attributes & SVGA_GRAPHICS_MODE)
  72.     {
  73.     switch (s->depth)
  74.     {
  75.         case 15:
  76.         case 16:
  77.         case 24:
  78.         RGB32Shift[0]    = s->red_shift;
  79.         RGB32Shift[1]    = s->green_shift;
  80.         RGB32Shift[2]    = s->blue_shift;
  81.         RGB32Bits[0]    = s->red_bits;
  82.         RGB32Bits[1]    = s->green_bits;
  83.         RGB32Bits[2]    = s->blue_bits;
  84.         break;
  85.  
  86.         default:
  87.         break;
  88.     }
  89.     }
  90.  
  91.     SVGAModeInfo    = s;
  92.     return 0;
  93. }
  94.  
  95. svga_mode_supported(
  96.     int        mode
  97.     )
  98. {
  99.     VBiosSetMode(mode | 0x80);
  100.     return (VBiosGetMode() & 0x7f) == mode;
  101. }
  102.  
  103. /*
  104.  * svga_setpalette()
  105.  */
  106. static void
  107. svga_setpalette(
  108.     color_t    *colormap,
  109.     int        ncolors
  110.     )
  111. {
  112.     int     i;
  113.  
  114.     inb(0x3da);
  115.     for (i = 0; i < 16; i++)
  116.     {
  117.     outb(0x3c0, i);
  118.     outb(0x3c0, i);
  119.     }
  120.  
  121.     inb(0x3da);
  122.     outb(0x3c8, 0);
  123.     while (--ncolors >= 0)
  124.     {
  125.     outb(0x3c9, RGB8Lookup[0][colormap->red] >> 2);
  126.     outb(0x3c9, RGB8Lookup[1][colormap->green] >> 2);
  127.     outb(0x3c9, RGB8Lookup[2][colormap->blue] >> 2);
  128.     colormap++;
  129.     }
  130.     outb(0x3c0, 0x20);
  131. }
  132.  
  133. static void
  134. svga_putpixels8(
  135.     int        x,
  136.     int        y,
  137.     unsigned char    *pixels,
  138.     int        npixels
  139.     )
  140. {
  141.     struct svga_mode_info    *s    = SVGAModeInfo;
  142.     int        bank;
  143.     long    offset;
  144.  
  145.     offset = y * s->scanline_length + x;
  146.  
  147.     if (s->window_size > 0)
  148.     {
  149.     bank    = offset / s->window_size;
  150.     offset    %= s->window_size;
  151.     bank    *= (s->window_size / s->window_granularity);
  152.  
  153.     (*s->window_control)(bank);
  154.  
  155.     while (offset + npixels > s->window_size)
  156.     {
  157.         int        n;
  158.  
  159.         n        = s->window_size - offset;
  160.         memcpy(s->window_address + offset, pixels, n);
  161.         offset    = 0;
  162.         pixels    += n;
  163.         npixels    -= n;
  164.         bank    += (s->window_size / s->window_granularity);
  165.         (*s->window_control)(bank);
  166.     }
  167.     }
  168.  
  169.     memcpy(s->window_address + offset, pixels, npixels);
  170. }
  171.  
  172. static void
  173. svga_putpixels24(
  174.     int        x,
  175.     int        y,
  176.     unsigned char    *pixels,
  177.     int        npixels
  178.     )
  179. {
  180.     switch (SVGAModeInfo->depth)
  181.     {
  182.     case 8:
  183.         svga_putpixels24to8(x, y, pixels, npixels);
  184.         break;
  185.  
  186.     case 15:
  187.     case 16:
  188.         svga_putpixels24to16(x, y, pixels, npixels);
  189.         break;
  190.  
  191.     case 24:
  192.         svga_putpixels24to24(x, y, pixels, npixels);
  193.         break;
  194.     }
  195. }
  196.  
  197. svga_putpixels24to8(
  198.     int        x,
  199.     int        y,
  200.     unsigned char    *pixels,
  201.     int        npixels
  202.     )
  203. {
  204.     struct svga_mode_info    *s    = SVGAModeInfo;
  205.     int        bank;
  206.     long    offset;
  207.  
  208.     offset = y * s->scanline_length + x;
  209.  
  210.     if (s->window_size > 0)
  211.     {
  212.     bank    = offset / s->window_size;
  213.     offset    %= s->window_size;
  214.     bank    *= (s->window_size / s->window_granularity);
  215.  
  216.     (*s->window_control)(bank);
  217.  
  218.     while (offset + npixels > s->window_size)
  219.     {
  220.         int        n;
  221.  
  222.         n        = s->window_size - offset;
  223.         CopyPixels24to8(pixels, s->window_address + offset, n, VPixelLookup);
  224.         offset    = 0;
  225.         pixels    += n * 3;
  226.         npixels    -= n;
  227.         bank    += (s->window_size / s->window_granularity);
  228.         (*s->window_control)(bank);
  229.     }
  230.     }
  231.  
  232.     CopyPixels24to8(pixels, s->window_address + offset, npixels, VPixelLookup);
  233. }
  234.  
  235. svga_putpixels24to16(
  236.     int        x,
  237.     int        y,
  238.     unsigned char    *pixels,
  239.     int        npixels
  240.     )
  241. {
  242.     struct svga_mode_info    *s    = SVGAModeInfo;
  243.     int        bank;
  244.     long    offset;
  245.  
  246.     offset = (y * s->scanline_length) + (x * 2);
  247.  
  248.     if (s->window_size > 0)
  249.     {
  250.     bank    = offset / s->window_size;
  251.     offset    %= s->window_size;
  252.     bank    *= (s->window_size / s->window_granularity);
  253.  
  254.     (*s->window_control)(bank);
  255.  
  256.     while (offset + npixels*2 > s->window_size)
  257.     {
  258.         int        n;
  259.  
  260.         n        = (s->window_size - offset) / 2;
  261.         GammaCopyPixels24to16(pixels, s->window_address + offset, n);
  262.         offset    = 0;
  263.         pixels    += n * 3;
  264.         npixels    -= n;
  265.         bank    += (s->window_size / s->window_granularity);
  266.         (*s->window_control)(bank);
  267.     }
  268.     }
  269.     GammaCopyPixels24to16(pixels, s->window_address + offset, npixels);
  270. }
  271.  
  272. svga_putpixels24to24(
  273.     int        x,
  274.     int        y,
  275.     unsigned char    *pixels,
  276.     int        npixels
  277.     )
  278. {
  279.     struct svga_mode_info    *s    = SVGAModeInfo;
  280.     int        bank;
  281.     long    offset;
  282.     int        n;
  283.  
  284.     offset = (y * s->scanline_length) + (x * 3);
  285.  
  286.     if (s->window_size > 0)
  287.     {
  288.     bank    = offset / s->window_size;
  289.     offset    %= s->window_size;
  290.     bank    *= (s->window_size / s->window_granularity);
  291.  
  292.     (*s->window_control)(bank);
  293.  
  294.     if (offset + npixels*3 >= s->window_size)
  295.     {
  296.         extern void        *alloca(int);
  297.         unsigned char    *tmp = alloca(npixels * 3);
  298.  
  299.         GammaCopyPixels24to24(pixels, tmp, npixels);
  300.         n    = s->window_size - offset;
  301.         memcpy(s->window_address + offset, tmp, n);
  302.         tmp    += n;
  303.         n    = (npixels * 3) - n;
  304.         bank += (s->window_size / s->window_granularity);
  305.         (*s->window_control)(bank);
  306.         memcpy(s->window_address, tmp, n);
  307.     }
  308.     else
  309.     {
  310.         GammaCopyPixels24to24(pixels, s->window_address + offset, npixels);
  311.     }
  312.     }
  313.     else
  314.     {
  315.         GammaCopyPixels24to24(pixels, s->window_address + offset, npixels);
  316.     }
  317. }
  318.  
  319. /*
  320.  * svga_puttext()
  321.  */
  322. static void
  323. svga_puttext(
  324.     int            x,
  325.     int            y,
  326.     register byte_t    *buf,
  327.     int            nbytes
  328.     )
  329. {
  330.     struct svga_mode_info    *s    = SVGAModeInfo;
  331.  
  332.     memcpy(s->window_address + (y * s->scanline_length) + (x * 2), buf, nbytes);
  333. }
  334.  
  335. static void
  336. svga_clear(
  337.     int        bg
  338.     )
  339. {
  340.     struct svga_mode_info    *s    = SVGAModeInfo;
  341.  
  342.     long    nbytes;
  343.  
  344.     nbytes    = s->scanline_length * s->height;
  345.  
  346.     if (s->attributes & SVGA_TEXT_MODE)    /* text mode    */
  347.     {
  348.     memset(s->window_address, bg | (bg << 4), nbytes);
  349.     }
  350.     else
  351.     {
  352.     int    bank;
  353.     int    step;
  354.  
  355.     step    = (s->window_size / s->window_granularity);
  356.  
  357.  
  358.     if (s->window_size > 0)
  359.     {
  360.         long    n;
  361.         for (bank = 0; nbytes > 0; bank += step)
  362.         {
  363.         (*s->window_control)(bank);
  364.         n = nbytes > s->window_size ? s->window_size : nbytes;
  365.         memset(s->window_address, bg, n);
  366.         nbytes -= n;
  367.         }
  368.     }
  369.     else
  370.         memset(s->window_address, bg, nbytes);
  371.  
  372.     }
  373. }
  374.  
  375. /*
  376.  * svga_setup()    - common setup code called by card-specific init routines
  377.  */
  378. int
  379. svga_setup(
  380.     struct vdev            *v,
  381.     struct svga_mode_info    *svga_modes,
  382.     void            (*win_ctl)()
  383.     )
  384. {
  385.     int                i;
  386.     struct svga_mode_info    *s;
  387.     vmode_t            *m;
  388.  
  389.     /*
  390.      * set up default values for anything not explicitly initialised already
  391.      */
  392.     SVGAMaxModeIndex    = 0;
  393.     SVGAModeTable    = svga_modes;
  394.  
  395.  
  396.     for (s = svga_modes; s->attributes != 0; s++)
  397.     {
  398.     SVGAMaxModeIndex++;
  399.  
  400.     if (s->scanline_length == 0)
  401.     {
  402.         int        n;
  403.  
  404.         n = (s->attributes & SVGA_TEXT_MODE) ? 2 : ((s->depth + 7) / 8);
  405.         s->scanline_length = s->width * n;
  406.     }
  407.  
  408.     if (s->window_address == 0)
  409.     {
  410.         if (s->attributes & SVGA_TEXT_MODE)
  411.         s->window_address = (void *) 0xB8000;
  412.         else
  413.         s->window_address = (void *) 0xA0000;
  414.     }
  415.  
  416.     if (s->window_size == 0)
  417.         s->window_size = 0x10000;
  418.  
  419.     if (s->window_granularity == 0)
  420.         s->window_granularity = s->window_size;
  421.  
  422.     if (s->window_control == 0)
  423.         s->window_control = win_ctl;
  424.  
  425.     if (s->depth > 8 && (s->red_bits | s->green_bits | s->blue_bits) == 0)
  426.     {
  427.         switch (s->depth)
  428.         {
  429.         case 15:
  430.             s->red_bits        = 5;
  431.             s->green_bits    = 5;
  432.             s->blue_bits    = 5;
  433.             s->red_shift    = 10;
  434.             s->green_shift    = 5;
  435.             s->blue_shift    = 0;
  436.             break;
  437.  
  438.         case 16:
  439.             s->red_bits        = 5;
  440.             s->green_bits    = 6;
  441.             s->blue_bits    = 5;
  442.             s->red_shift    = 11;
  443.             s->green_shift    = 5;
  444.             s->blue_shift    = 0;
  445.             break;
  446.  
  447.         case 24:
  448.             s->red_bits        = 8;
  449.             s->green_bits    = 8;
  450.             s->blue_bits    = 8;
  451.             s->red_shift    = 16;
  452.             s->green_shift    = 8;
  453.             s->blue_shift    = 0;
  454.             break;
  455.         }
  456.     }
  457.     }
  458.  
  459.     m    = (vmode_t *) malloc(sizeof(vmode_t) * (SVGAMaxModeIndex + 1));
  460.     if (m == 0)
  461.     fatal(0, "can't allocate memory for mode table");
  462.  
  463.     v->v_modes    = m;
  464.     s        = svga_modes;
  465.     for (i = 0; i <= SVGAMaxModeIndex; i++, m++, s++)
  466.     {
  467.     m->width    = s->width;
  468.     m->height    = s->height;
  469.     m->depth    = s->depth;
  470.     m->flags    = 0;
  471.     if (s->attributes & SVGA_MODE_SUPPORTED)
  472.         m->flags    |= V_MODE_SUPPORTED;
  473.     if (s->attributes & SVGA_TEXT_MODE)
  474.         m->flags    |= V_TEXT_MODE;
  475.     if (s->attributes & SVGA_GRAPHICS_MODE)
  476.         m->flags    |= V_GRAPHICS_MODE;
  477.     }
  478.    
  479.     v->v_reset        = svga_reset;
  480.     v->v_setmode    = svga_setmode;
  481.     v->v_setpalette    = svga_setpalette;
  482.     v->v_clear        = svga_clear;
  483.     v->v_putpixels8    = svga_putpixels8;
  484.     v->v_putpixels24    = svga_putpixels24;
  485.     v->v_puttext    = svga_puttext;
  486.  
  487.     svga_bios_initial_mode    = VBiosGetMode();
  488.  
  489.     return 0;
  490. }
  491.